package com.devops.service.impl;


import com.devops.entity.JvmDesc;
import com.devops.service.JvmDescService;
import com.sun.management.OperatingSystemMXBean;
import org.springframework.stereotype.Service;

import java.lang.management.*;
import java.text.DecimalFormat;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author huang
 * @Description
 * @Date 2025/7/5 15:21
 */
@Service
public class JvmDescServiceImpl implements JvmDescService {

    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.00");

    @Override
    public JvmDesc getJvmDesc() {
        //  物理内存（真实系统内存）
        OperatingSystemMXBean osBean = (OperatingSystemMXBean)
                ManagementFactory.getOperatingSystemMXBean();
        long physicalTotal = osBean.getTotalPhysicalMemorySize();
        long physicalFree = osBean.getFreePhysicalMemorySize();
        long physicalUsed = physicalTotal - physicalFree;

        //  JVM 堆内存
        MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage heap = memoryMxBean.getHeapMemoryUsage();
        long jvmTotal = heap.getCommitted();
        long jvmUsed = heap.getUsed();
        long jvmFree = jvmTotal - jvmUsed;

        //  JVM 参数信息
        RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();

        //  GC 信息
        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
        String gcInfo = gcBeans.stream()
                .map(gc -> gc.getName() + ": count=" + gc.getCollectionCount()
                        + ", time=" + gc.getCollectionTime() + "ms")
                .collect(Collectors.joining(" | "));

        //  线程信息
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

        //  类加载信息
        ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();

        return JvmDesc.builder()
                .memoryTotal(formatBytes(physicalTotal))
                .memoryUsed(formatBytes(physicalUsed))
                .memoryFree(formatBytes(physicalFree))
                .jvmMemoryTotal(formatBytes(jvmTotal))
                .jvmMemoryUsed(formatBytes(jvmUsed))
                .jvmMemoryFree(formatBytes(jvmFree))
                .jvmVersion(runtimeMxBean.getSpecVersion())
                .jvmVendor(runtimeMxBean.getVmVendor())
                .jvmName(runtimeMxBean.getVmName())
                .inputArgs(String.join(" ", runtimeMxBean.getInputArguments()))
                .threadCount(threadMXBean.getThreadCount())
                .loadedClassCount(classLoadingMXBean.getLoadedClassCount())
                .gcInfo(gcInfo)
                .build();
    }

    private String formatBytes(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return DECIMAL_FORMAT.format(bytes / 1024.0) + " KB";
        } else if (bytes < 1024L * 1024 * 1024) {
            return DECIMAL_FORMAT.format(bytes / 1024.0 / 1024.0) + " MB";
        } else {
            return DECIMAL_FORMAT.format(bytes / 1024.0 / 1024.0 / 1024.0) + " GB";
        }
    }
}
